package com.example.makerspace.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.makerspace.controller.maker.vo.*;
import com.example.makerspace.domain.*;
import com.example.makerspace.dto.PageResult;
import com.example.makerspace.dto.Pagination;
import com.example.makerspace.dto.Result;
import com.example.makerspace.dto.maker.StatusTImesDTO;
import com.example.makerspace.dto.maker.TaskBaseDTO;
import com.example.makerspace.dto.maker.TaskQueryDTO;
import com.example.makerspace.enums.maker.ModelEnum;
import com.example.makerspace.enums.maker.StatusInEnum;
import com.example.makerspace.enums.maker.StatusOutEnum;
import com.example.makerspace.enums.maker.TimeEnum;
import com.example.makerspace.mapper.*;
import com.example.makerspace.service.TaskService;
import com.example.makerspace.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jdk.net.SocketFlow;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import static com.example.makerspace.enums.ResultCodeEnum.FOLLOW_CANCEL;
import static com.example.makerspace.enums.ResultCodeEnum.FOLLOW_EXIST;
import static com.example.makerspace.utils.JwtUtils.parseToken;

@Service
public class TaskServiceImpl implements TaskService {

    @Autowired
    private AreaMapper areaMapper;

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private TaskStatusMapper taskStatusMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TaskFollowMapper taskFollowMapper;

    @Override
    public Result queryCatalog() {
        CatalogVO catalogVO = new CatalogVO();
        QueryWrapper<AreaDO> queryWrapper = new QueryWrapper();
        List<AreaDO> areaDOS = areaMapper.selectList(queryWrapper);
        List<AreaVO> areaVOS = new ArrayList<>();
        List<ModelVO> modelVOS = new ArrayList<>();
        List<StatusVO> statusVOS = new ArrayList<>();
        List<TimeVO> timeVOS = new ArrayList<>();
        for (AreaDO areaDO : areaDOS) {
            areaVOS.add(AreaVO.builder()
                    .areaId(areaDO.getId())
                    .areaName(areaDO.getAreaName())
                    .build());
        }
        for (StatusOutEnum value : StatusOutEnum.values()) {
            statusVOS.add(StatusVO.builder()
                    .statusId(value.getStatusId())
                    .statusName(value.getStatusName())
                    .build());
        }
        for (ModelEnum value : ModelEnum.values()) {
            modelVOS.add(ModelVO.builder()
                    .modelId(value.getModelId())
                    .modelName(value.getModelName())
                    .build());
        }
        for (TimeEnum value : TimeEnum.values()) {
            timeVOS.add(TimeVO.builder()
                    .timeId(value.getTimeId())
                    .timeName(value.getTimeName())
                    .build());
        }
        catalogVO.setAreas(areaVOS);
        catalogVO.setModels(modelVOS);
        catalogVO.setStatus(statusVOS);
        catalogVO.setTimes(timeVOS);
        return Result.success(catalogVO);
    }

    @Override
    public Result queryInStatus() {
        List<StatusVO> statusVOS = new ArrayList<>();
        for (StatusInEnum value : StatusInEnum.values()) {
            statusVOS.add(StatusVO.builder()
                    .statusId(value.getStatusId())
                    .statusName(value.getStatusName())
                    .build());
        }
        return Result.success(statusVOS);
    }

    @Override
    @Transactional
    public Result create(TaskBaseDTO taskBaseDTO, HttpServletRequest request) {
        TaskDO taskDO = new TaskDO();
        taskDO.setAreaId(taskBaseDTO.getAreaId());
        taskDO.setModelId(taskBaseDTO.getModelId());
        taskDO.setStatusId(StatusOutEnum.RESULTS_COLLECTION.getStatusId());
        taskDO.setTaskName(taskBaseDTO.getTaskName());
        taskDO.setViewCount(0);
        String id = JwtUtils.getUserID(request);
        taskDO.setCreateUserId(Integer.valueOf(id));
        taskDO.setTaskContent(taskBaseDTO.getTaskContent());
        taskDO.setFollowNum(0);
        taskDO.setPrice(taskBaseDTO.getPrice());
        taskMapper.insert(taskDO);
        //添加状态
        for (StatusTImesDTO statusTime : taskBaseDTO.getStatusTimes()) {
            TaskStatusDO taskStatusDO = new TaskStatusDO();
            taskStatusDO.setTaskId(taskDO.getId());
            taskStatusDO.setStatusId(statusTime.getStatusId());
            taskStatusDO.setDuration(statusTime.getDuration());
            taskStatusMapper.insert(taskStatusDO);
        }
        return Result.success(true);
    }

    @Override
    public Result update(TaskBaseDTO taskBaseDTO) {
        TaskDO taskDO = new TaskDO();
        taskDO.setId(taskBaseDTO.getId());
        taskDO.setAreaId(taskBaseDTO.getAreaId());
        taskDO.setModelId(taskBaseDTO.getModelId());
        taskDO.setStatusId(StatusOutEnum.RESULTS_COLLECTION.getStatusId());
        taskDO.setTaskName(taskBaseDTO.getTaskName());
        taskDO.setTaskContent(taskBaseDTO.getTaskContent());
        taskDO.setPrice(taskDO.getPrice());
        taskDO.setModifyTime(new Date());
        taskMapper.updateById(taskDO);
        //删除状态
        taskStatusMapper.delete(new QueryWrapper<TaskStatusDO>().eq("task_id", taskDO.getId()));
        //添加状态
        for (StatusTImesDTO statusTime : taskBaseDTO.getStatusTimes()) {
            TaskStatusDO taskStatusDO = new TaskStatusDO();
            taskStatusDO.setTaskId(taskDO.getId());
            taskStatusDO.setStatusId(statusTime.getStatusId());
            taskStatusDO.setDuration(statusTime.getDuration());
            taskStatusMapper.insert(taskStatusDO);
        }
        return Result.success();
    }

    @Override
    public Result query(TaskQueryDTO taskQueryDTO) {
        QueryWrapper<TaskDO> queryWrapper = new QueryWrapper<>();
        if (taskQueryDTO.getStatusId() != null) {
            queryWrapper.eq("status_id", taskQueryDTO.getStatusId());
        }
        if (!StringUtils.isEmpty(taskQueryDTO.getName())) {
            queryWrapper.like("task_name", taskQueryDTO.getName());
        }
        if (taskQueryDTO.getModelId() != null) {
            queryWrapper.eq("model_id", taskQueryDTO.getModelId());
        }
        if (taskQueryDTO.getAreaId() != null) {
            queryWrapper.eq("area_id", taskQueryDTO.getAreaId());
        }
        if (taskQueryDTO.getLastest() != null) {
            if (taskQueryDTO.getLastest()) {
                queryWrapper.orderByDesc("create_time");
            } else {
                queryWrapper.orderByAsc("create_time");
            }
        }
        if (taskQueryDTO.getHotest() != null) {
            if (taskQueryDTO.getHotest()) {
                queryWrapper.orderByDesc("view_count");
            } else {
                queryWrapper.orderByAsc("view_count");
            }
        }
        if (taskQueryDTO.getPriceMark() != null) {
            if (taskQueryDTO.getPriceMark()) {
                queryWrapper.orderByDesc("price");
            } else {
                queryWrapper.orderByAsc("price");
            }
        }
        if (taskQueryDTO.getPublishStatus() != null) {
            queryWrapper.eq("publish_status", taskQueryDTO.getPublishStatus());
        }
        // 时间筛选
        if (taskQueryDTO.getTimeId() != null) {
            if (taskQueryDTO.getTimeId().equals(TimeEnum.THREE_DAY.getTimeId())) {
                //3天内到期的
                int minutes = 24 * 60 * 3; //3天分钟数
                //查询当前阶段小于3天的
                queryWrapper.le("remainder", minutes);
                queryWrapper.ne("status_id", StatusOutEnum.COMPLETED.getStatusId());//排除最后阶段
                queryWrapper.isNotNull("remainder");
            } else if (taskQueryDTO.getTimeId().equals(TimeEnum.ONE_DAY.getTimeId())) {
                //3天内到期的
                int minutes = 24 * 60 * 1; //1天分钟数
                //查询当前阶段小于3天的
                queryWrapper.le("remainder", minutes);
                queryWrapper.isNotNull("remainder");
                queryWrapper.ne("status_id", StatusOutEnum.COMPLETED.getStatusId());//排除最后阶段
            } else if (taskQueryDTO.getTimeId().equals(TimeEnum.SEVEN_DAY.getTimeId())) {
                //3天内到期的
                int minutes = 24 * 60 * 7; //1天分钟数
                //查询当前阶段小于3天的
                queryWrapper.le("remainder", minutes);
                queryWrapper.isNotNull("remainder");
                queryWrapper.ne("status_id", StatusOutEnum.COMPLETED.getStatusId());//排除最后阶段
            }
        }

        Page<TaskDO> page = new Page<>(taskQueryDTO.getPagination().getPageNum(), taskQueryDTO.getPagination().getSize());
        Page<TaskDO> taskDOPage = taskMapper.selectPage(page, queryWrapper);
        PageResult pageResult = PageResult.success();
        Pagination pagination = Pagination.builder()
                .size(page.getSize())
                .pageNum(taskQueryDTO.getPagination().getPageNum())
                .total(taskDOPage.getTotal())
                .totalPages(taskDOPage.getPages())
                .build();
        pageResult.setPagination(pagination);
        List<TaskBaseVO> taskBaseVOS = new ArrayList<>();
        for (TaskDO taskDO : taskDOPage.getRecords()) {
            QueryWrapper<TaskStatusDO> taskStatusDOQueryWrapper = new QueryWrapper<>();
            taskStatusDOQueryWrapper.eq("task_id", taskDO.getId());
            List<TaskStatusDO> taskStatusDOS = taskStatusMapper.selectList(taskStatusDOQueryWrapper);
            List<StatusTImesDTO> statusTImesDTOS = new ArrayList<>();
            taskStatusDOS.sort(Comparator.comparing(TaskStatusDO::getStatusId));
            String remainder = "剩余" + taskDO.getRemainder() / 60 + "时" + taskDO.getRemainder() % 60 + "分";
            if (taskDO.getStatusId().equals(StatusInEnum.COMPLETED.getStatusId())) {
                remainder = null;
            }

            for (TaskStatusDO taskStatusDO : taskStatusDOS) {
                statusTImesDTOS.add(StatusTImesDTO.builder()
                        .statusId(taskStatusDO.getStatusId())
                        .duration(taskStatusDO.getTaskId().equals(StatusOutEnum.COMPLETED.getStatusId()) ? 0 : taskStatusDO.getDuration())
                        .build());
            }
            UserDO userDO = userMapper.selectById(taskDO.getCreateUserId());
            String username = null;
            if (userDO != null) {
                username = userDO.getNickname();
            }
            TaskBaseVO taskBaseVO = TaskBaseVO.builder()
                    .areaId(taskDO.getAreaId())
                    .modelId(taskDO.getModelId())
                    .statusId(taskDO.getStatusId())
                    .taskName(taskDO.getTaskName())
                    .viewCount(taskDO.getViewCount())
                    .createUserId(taskDO.getCreateUserId())
                    .taskContent(taskDO.getTaskContent())
                    .followNum(taskDO.getFollowNum())
                    .createName(username)
                    .remainder(remainder)
                    .price(taskDO.getPrice())
                    .publishStatus(taskDO.getPublishStatus())
                    .statusTimes(statusTImesDTOS)
                    .build();
            taskBaseVO.setId(taskDO.getId());
            taskBaseVO.setCreateTime(taskDO.getCreateTime());
            taskBaseVO.setModifyTime(taskDO.getModifyTime());
            taskBaseVOS.add(taskBaseVO);
        }

        pageResult.setObj(taskBaseVOS);
        return pageResult;
    }

    @Override
    public Result queryById(Integer id, HttpServletRequest request) {
        TaskDO taskDO = taskMapper.selectById(id);
        QueryWrapper<TaskStatusDO> taskStatusDOQueryWrapper = new QueryWrapper<>();
        taskStatusDOQueryWrapper.eq("task_id", taskDO.getId());
        List<TaskStatusDO> taskStatusDOS = taskStatusMapper.selectList(taskStatusDOQueryWrapper);
        List<StatusTImesDTO> statusTImesDTOS = new ArrayList<>();
        taskStatusDOS.sort(Comparator.comparing(TaskStatusDO::getStatusId));
        String remainder = "剩余" + taskDO.getRemainder() / 60 + "时" + taskDO.getRemainder() % 60 + "分";
        if (taskDO.getStatusId().equals(StatusInEnum.COMPLETED.getStatusId())) {
            remainder = null;
        }

        for (TaskStatusDO taskStatusDO : taskStatusDOS) {
            statusTImesDTOS.add(StatusTImesDTO.builder()
                    .statusId(taskStatusDO.getStatusId())
                    .duration(taskStatusDO.getTaskId().equals(StatusOutEnum.COMPLETED.getStatusId()) ? 0 : taskStatusDO.getDuration())
                    .build());
        }
        UserDO userDO = userMapper.selectById(taskDO.getCreateUserId());
        String username = null;
        if (userDO != null) {
            username = userDO.getNickname();
        }
        String token = request.getHeader("token");
        Boolean follow = null;
        if (!StringUtils.isEmpty(token)) {
            Claims claims = parseToken(token);
            String userId = (String) claims.get("id");
            QueryWrapper<TaskFollowDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("task_id", id);
            queryWrapper.eq("user_id", userId);
            List<TaskFollowDO> taskFollowDOS = taskFollowMapper.selectList(queryWrapper);
            if (taskFollowDOS.isEmpty()) {
                follow = false;
            } else {
                follow = true;
            }
        }


        TaskBaseVO taskBaseVO = TaskBaseVO.builder()
                .areaId(taskDO.getAreaId())
                .modelId(taskDO.getModelId())
                .statusId(taskDO.getStatusId())
                .taskName(taskDO.getTaskName())
                .viewCount(taskDO.getViewCount())
                .createUserId(taskDO.getCreateUserId())
                .taskContent(taskDO.getTaskContent())
                .followNum(taskDO.getFollowNum())
                .createName(username)
                .remainder(remainder)
                .price(taskDO.getPrice())
                .publishStatus(taskDO.getPublishStatus())
                .statusTimes(statusTImesDTOS)
                .follow(follow)
                .build();
        taskBaseVO.setId(taskDO.getId());
        taskBaseVO.setCreateTime(taskDO.getCreateTime());
        taskBaseVO.setModifyTime(taskDO.getModifyTime());
        return Result.success(taskBaseVO);
    }

    @Override
    public Result delete(Integer id) {
        taskMapper.deleteById(id);
        taskStatusMapper.delete(new QueryWrapper<TaskStatusDO>().eq("task_id", id));
        return Result.success(true);
    }

    @Override
    public Result updatePublishStatus(TaskBaseDTO taskBaseDTO) {
        TaskDO taskDO = new TaskDO();
        taskDO.setId(taskBaseDTO.getId());
        taskDO.setPublishStatus(taskBaseDTO.getPublishStatus());
        taskDO.setModifyTime(new Date());
        taskMapper.updateById(taskDO);
        return null;
    }

    @Override
    public Result addView(Integer id) {
        TaskDO taskDO = taskMapper.selectById(id);
        taskDO.setViewCount(taskDO.getViewCount() + 1);
        taskMapper.updateById(taskDO);
        return Result.success(true);
    }

    @Override
    @Transactional
    public Result follow(Integer id, HttpServletRequest request) {
        QueryWrapper<TaskFollowDO> queryWrapper = new QueryWrapper<>();
        String userID = JwtUtils.getUserID(request);
        queryWrapper.eq("task_id", id);
        queryWrapper.eq("user_id", userID);

        List<TaskFollowDO> taskFollowDOS = taskFollowMapper.selectList(queryWrapper);
        if (taskFollowDOS.size() > 0) {
            return Result.error(FOLLOW_EXIST);
        }

        TaskFollowDO taskFollowDO = new TaskFollowDO();
        taskFollowDO.setUserId(Integer.valueOf(JwtUtils.getUserID(request)));
        taskFollowDO.setTaskId(id);
        taskFollowMapper.insert(taskFollowDO);
        TaskDO taskDO = taskMapper.selectById(id);
        taskDO.setFollowNum(taskDO.getFollowNum() + 1);
        taskMapper.updateById(taskDO);
        return Result.success(true);
    }

    @Override
    @Transactional
    public Result cancelFollow(Integer id, HttpServletRequest request) {
        QueryWrapper<TaskFollowDO> deleteQueryWrapper = new QueryWrapper<>();
        String userID = JwtUtils.getUserID(request);
        deleteQueryWrapper.eq("task_id", id);
        deleteQueryWrapper.eq("user_id", userID);
        List<TaskFollowDO> taskFollowDOS = taskFollowMapper.selectList(deleteQueryWrapper);
        if (taskFollowDOS.size() > 0) {
            return Result.error(FOLLOW_CANCEL);
        }
        taskFollowMapper.delete(deleteQueryWrapper);
        TaskDO taskDO = taskMapper.selectById(id);
        taskDO.setFollowNum(taskDO.getFollowNum() - 1);
        taskMapper.updateById(taskDO);
        return Result.success(true);
    }


}
